package de.karlNet.sambamanager.ldapController.commands.attributeBuilder;

import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;

import javax.naming.directory.BasicAttribute;
import javax.naming.directory.BasicAttributes;

import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import org.springframework.stereotype.Controller;

import de.karlNet.sambamanager.ldapModel.dns.LdapDNSCName;
@Controller
@Scope(value = "session", proxyMode = ScopedProxyMode.TARGET_CLASS)
public class CNameRecordBuilder {
	public BasicAttributes buildARecordAttributesWithDC(LdapDNSCName ldapDNSARecord) throws UnsupportedEncodingException {
		BasicAttributes basicAttributes = new BasicAttributes();
		for (BasicAttribute attribute : this.buildARecordAttributeListWithDC(
				ldapDNSARecord)) {
			basicAttributes.put(attribute);
		}
		return basicAttributes;
	}

	public List<BasicAttribute> buildARecordAttributeListWithDC(LdapDNSCName ldapDNSARecord) throws UnsupportedEncodingException {
		List<BasicAttribute> attributes = this.buildARecordAttributeList(ldapDNSARecord);
		BasicAttribute samaccountname = new BasicAttribute("dc",
				ldapDNSARecord.getCn());
		attributes.add(samaccountname);
		return attributes;
	}
	
	public List<BasicAttribute> buildARecordAttributeList(
			LdapDNSCName ldapDNSARecord) throws UnsupportedEncodingException {
		ArrayList<BasicAttribute> attributes = new ArrayList<BasicAttribute>();
	

		BasicAttribute objectClass = new BasicAttribute("objectclass");
		objectClass.add("dnsNode");
		attributes.add(objectClass);

		BasicAttribute dnsRecord = new BasicAttribute("dnsRecord");
		dnsRecord.add(this.createRawData(ldapDNSARecord));
		attributes.add(dnsRecord);

		return attributes;
	}
	
	public byte[] createRawData(LdapDNSCName ldapDNSCName) throws UnsupportedEncodingException {
		ByteBuffer buffer = ByteBuffer.allocate(4);
        buffer.putInt(ldapDNSCName.getTtl());
        byte[] ttlArray = buffer.array();
        
        String[] aliasParts = ldapDNSCName.getAliasFor().split("\\.");
        
        byte[] cnameBytes = ldapDNSCName.getAliasFor().getBytes("US-ASCII");
        int[] aliasData = new int[cnameBytes.length +1];
		for (int i = 0; i < aliasData.length - 1; i++) {
			aliasData[i] = cnameBytes[i] & 0xFF;
		}
		aliasData[aliasData.length-1] = 0;
		int rdataLength0 = aliasData.length & 0xFF;
		int rdataLength1 = aliasData.length >> 8 & 0xFF;
		int[] dnsRecordRawInt = { 
				rdataLength0,  
				rdataLength1, 
				2, // type0 = cname according to iana
				0x00, // type1 
				
				0x05, // unknown 0
				0xf0, // unknown 1 
				0x00, // unknown 2
				0x00, // unknown 3
				
				0x01, // unknown 4  
				0x00, // unknown 5 
				0x00, // unknown 6 
				0x00, // unknown 8 
				
				ttlArray[0] & 0xFF, 
				ttlArray[1] & 0xFF, 
				ttlArray[2] & 0xFF, 
				ttlArray[3] & 0xFF, 
				
				0x00,
				0x00, 
				0x00, 
				0x00, 
				
				0x00, 
				0x00, 
				0x00, 
				0x00, 
		};
		int[] rdataHeader = {
				aliasData.length + 1 ,
				1,
				aliasParts[0].getBytes("US-ASCII").length
		};
		
		byte[] dnsRecordRaw = new byte[dnsRecordRawInt.length
				+ rdataHeader.length + aliasData.length];
		// copy dnsRecordRawInt
		for (int i = 0; i < dnsRecordRawInt.length; i++) {
			dnsRecordRaw[i] = (byte)(dnsRecordRawInt[i]);
		}
		// copy rdataHeader
		for(int i=0;i<rdataHeader.length;i++) {
			dnsRecordRaw[i + dnsRecordRawInt.length] = (byte) rdataHeader[i];
		}
		// copy data
		for(int i=0;i<aliasData.length;i++) {
			dnsRecordRaw[i + dnsRecordRawInt.length + rdataHeader.length] = (byte) aliasData[i];
		}
		
		return dnsRecordRaw;
	}
}
